package com.pb.infra.auth.service;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.pb.infra.auth.entity.custom.PriviInterCustom;
import com.pb.infra.auth.entity.custom.PriviMenuCustom;
import com.pb.infra.auth.mapper.CommonMapper;
import com.pb.infra.auth.mapper.custom.PriviMenuInterCustomMapper;
import com.pb.infra.auth.mapper.custom.PriviUserCustomMapper;
import com.pb.infra.oth.util.*;
import com.pb.infra.auth.entity.pbsys.PriviPositionRoleExample;
import com.pb.infra.auth.mapper.pbsys.PriviPositionRoleMapper;
import com.pb.infra.oth.entity.common.Page;
import com.pb.infra.oth.entity.common.Result;
import com.pb.infra.oth.entity.common.Tree;
import com.pb.infra.auth.entity.custom.PriviRoleCustom;
import com.pb.infra.auth.entity.pbsys.PriviRole;
import com.pb.infra.auth.entity.pbsys.PriviRoleMenu;
import com.pb.infra.auth.entity.pbsys.PriviRoleMenuExample;
import com.pb.infra.oth.exception.AppAuthException;
import com.pb.infra.oth.exception.ErrorCode;
import com.pb.infra.auth.mapper.custom.PriviRoleCustomMapper;
import com.pb.infra.auth.mapper.pbsys.PriviRoleMapper;
import com.pb.infra.auth.mapper.pbsys.PriviRoleMenuMapper;
import com.pb.infra.oth.service.SequenceGeneratorService;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 角色管理
 *
 * @author liudebao
 * @date 2020/1/1
 */
@Slf4j
@Service
public class PriviRoleService {

    /**
     * 角色单表DAO映射
     */
    @Resource
    private PriviRoleMapper roleMapper;

    /**
     * 角色多表DAO映射
     */
    @Resource
    private PriviRoleCustomMapper roleCustomMapper;

    /**
     * 角色菜单表DAO映射
     */
    @Resource
    private PriviRoleMenuMapper priviRoleMenuMapper;

    /**
     * 序号自动生成逻辑层
     */
    @Resource
    private SequenceGeneratorService sequenceGeneratorService;

    /**
     * 职位角色表DAO映射
     */
    @Resource
    private PriviPositionRoleMapper priviPositionRoleMapper;

    @Resource
    private PriviMenuInterCustomMapper priviMenuInterCustomMapper;

    @Resource
    private CommonMapper commonMapper;

    /**
     * jwttoken配置类
     */
    @Resource
    private JwtTokenConfig jwtTokenConfig;

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    /**
     * 用户多表DAO映射
     */
    @Resource
    private PriviUserCustomMapper userCustomMapper;

    /**
     * 查询角色信息
     *
     * @param condition
     * @param page
     * @return
     */
    public Result select(PriviRoleCustom condition, Page page, HttpServletRequest request) {
        if (page != null && page.getPageIndex() != null && page.getPageSize() != null) {
            PageHelper.startPage(page.getPageIndex(), page.getPageSize());
        }
        if (!StringUtil.isEmpty(condition.getLoginUser()) && Constant.OK.equals(condition.getLoginUser())) {
            String token = request.getHeader(jwtTokenConfig.getHeader());
            Claims claims = jwtTokenConfig.getClaimByToken(token);
            String userId = (String)claims.get(jwtTokenConfig.getSub());
            condition.setLoginUser(userId);
        }
        List<PriviRoleCustom> list = roleCustomMapper.select(condition);
        return Result.ok(new PageInfo(list).getTotal(), list);
    }

    /**
     * 新增角色
     *
     * @param priviRole 请求参数
     * @return Result   操作信息
     */

    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> insert(PriviRole priviRole, HttpServletRequest request) {
        Map<String, Object> map1 = new HashMap<>();
        try {
            //校验角色名称重复
            List<Map<String, Object>> list1 = roleCustomMapper.selRoleNameInfo(priviRole);
            if (list1 != null && list1.size() > 0) {
                throw new AppAuthException(ErrorCode.ErrorCodeEnum.ACCESS_ROLE_NAME);
            }
            String token = request.getHeader(jwtTokenConfig.getHeader());
            Claims claims = jwtTokenConfig.getClaimByToken(token);
            String userId = (String)claims.get(jwtTokenConfig.getSub());
            String seqId = sequenceGeneratorService.getNextIdStr("ROLE", "ROLE");
            priviRole.setRoleId(seqId);
            priviRole.setCreateUser(userId);
            priviRole.setUpdateUser(userId);
            priviRole.setCreateTime(DateTimeUtil.getStrFromNewDate());
            priviRole.setUpdateTime(DateTimeUtil.getStrFromNewDate());
            roleMapper.insertSelective(priviRole);
            /*
            新增角色所有按钮资源
             */
            map1.put("roleId", seqId);
            map1.put("userId", userId);
            map1.put("time", DateTimeUtil.getDate());
            roleCustomMapper.addBtnRes(map1);
            map1.put("code", Constant.OK);
            map1.put("msg", Constant.INSERT_OK_MSG);
        } catch (AppAuthException e) {
            map1.put("msg", e.getMessage());
            map1.put("code", e.getCode());
        }
        return map1;
    }

    /**
     * 修改角色
     *
     * @param priviRole 请求参数
     * @return Result   操作信息
     */

    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> update(PriviRole priviRole, HttpServletRequest request) {
        Map<String, Object> map1 = new HashMap<>();
        try {
            /*List<Map<String, Object>> list1 = roleCustomMapper.selRoleNameInfo(priviRole);
            if (list1 != null && list1.size() > 0) {
                throw new AppAuthException(ErrorCode.ErrorCodeEnum.ACCESS_ROLE_NAME);
            }*/
            String token = request.getHeader(jwtTokenConfig.getHeader());
            Claims claims = jwtTokenConfig.getClaimByToken(token);
            String userId = (String)claims.get(jwtTokenConfig.getSub());
            priviRole.setUpdateUser(userId);
            priviRole.setUpdateTime(DateTimeUtil.getStrFromNewDate());
            roleMapper.updateByPrimaryKeySelective(priviRole);
            map1.put("code", Constant.OK);
            map1.put("msg", Constant.UPDATE_OK_MSG);
        } catch (AppAuthException e) {
            map1.put("msg", e.getMessage());
            map1.put("code", e.getCode());
        }
        return map1;
    }

    /**
     * 删除角色
     *
     * @param priviRolList 请求参数
     * @return Result   操作信息
     */
    @Transactional(rollbackFor = Exception.class)
    public void delete(List<PriviRole> priviRolList, HttpServletRequest request) {
        for (PriviRole priviRole : priviRolList) {
            PriviPositionRoleExample priviPositionRoleExample = new PriviPositionRoleExample();
            PriviPositionRoleExample.Criteria criteria = priviPositionRoleExample.createCriteria();
            criteria.andRoleIdEqualTo(priviRole.getRoleId());
            priviPositionRoleMapper.deleteByExample(priviPositionRoleExample);
            PriviRoleMenuExample priviRoleMenuExample = new PriviRoleMenuExample();
            priviRoleMenuExample.createCriteria().andRoleIdEqualTo(priviRole.getRoleId());
            priviRoleMenuMapper.deleteByExample(priviRoleMenuExample);
            roleCustomMapper.delRoleRes(priviRole.getRoleId());
            roleMapper.deleteByPrimaryKey(priviRole.getRoleId());
        }
        String token = request.getHeader(jwtTokenConfig.getHeader());
        Claims claims = jwtTokenConfig.getClaimByToken(token);
        String userId = (String)claims.get(jwtTokenConfig.getSub());
        UserInfo userInfo = (UserInfo)redisTemplate.opsForValue().get(token);
        List<PriviRoleCustom> roleList = userCustomMapper.selRoleByUserId(userId);
        userInfo.setUserRoles(roleList);
        if (redisTemplate.hasKey(token)) {
            redisTemplate.delete(token);
        }
        redisTemplate.opsForValue().set(token, userInfo, 24L, TimeUnit.HOURS);
        // redisTemplate.opsForValue().set(token + "userRoles", roleList, 24L, TimeUnit.HOURS);
    }

    /**
     * 读取某个角色仍未配置的用户分页信息
     *
     * @param priviUserCustom 请求参数
     * @return Result 某个角色仍未配置的用户信息
     */
    /*public Result getRoleUserNotMapListByPage(PriviUserCustom priviUserCustom, Page page) {
        if (page != null && page.getPageIndex() != null && page.getPageSize() != null) {
            PageHelper.startPage(page.getPageIndex(), page.getPageSize());
        }
        List<PriviUserCustom> roleUserNotMapListByPage = roleCustomMapper.getRoleUserNotMapListByPage(priviUserCustom);
        return Result.ok(new PageInfo(roleUserNotMapListByPage).getTotal(), roleUserNotMapListByPage);
    }*/

    /**
     * 读取某角色配置的用户分页信息
     *
     * @param paramMap 请求参数
     * @return Map<String, Object> 某角色配置的用户信息
     */
    public Result getRoleUserListByPage(Map<String, Object> paramMap, Page page) {
        if (page != null && page.getPageIndex() != null && page.getPageSize() != null) {
            PageHelper.startPage(page.getPageIndex(), page.getPageSize());
        }
        List<Map<String, Object>> userList = roleCustomMapper.getRoleUserListByPage(paramMap);
        return Result.ok(new PageInfo(userList).getTotal(), userList);
    }

    /**
     * 读取某角色配置的菜单信息
     *
     * @param paramMap 请求参数
     * @return List<Map < String, Object>> 某角色配置的菜单信息
     */
    public Result getMenuByRoleId(Map<String, Object> paramMap) {
        List<Tree> menuList = new ArrayList<>();
        menuList = roleCustomMapper.getMenuByRoleId(paramMap);
        for (Tree menu : menuList) {
            menu.setChecked(Integer.parseInt(menu.getChecked().toString()) == 1);
        }
        return Result.ok(menuList);
    }

    /**
     * 保存角色配置的菜单信息
     *
     * @param paramMap 请求参数
     */
    @Transactional
    public void saveMenuAuth(Map<String, Object> paramMap, HttpServletRequest request) {
        String token = request.getHeader(jwtTokenConfig.getHeader());
        Claims claims = jwtTokenConfig.getClaimByToken(token);
        String userId = (String)claims.get(jwtTokenConfig.getSub());
        // 删除之前配置的菜单信息
        PriviRoleMenuExample priviRoleMenuExample = new PriviRoleMenuExample();
        PriviRoleMenuExample.Criteria criteria = priviRoleMenuExample.createCriteria();
        criteria.andRoleIdEqualTo(paramMap.get("roleId").toString());
        criteria.andAppIdEqualTo(paramMap.get("appId").toString());
        priviRoleMenuMapper.deleteByExample(priviRoleMenuExample);
        paramMap.put("user", userId);
        paramMap.put("time", DateTimeUtil.getDate());
        // 保存当前配置的菜单信息
        for (String menuId : (List<String>) paramMap.get("menuIds")) {
            PriviRoleMenu priviRoleMenu = new PriviRoleMenu();
            priviRoleMenu.setRoleId(paramMap.get("roleId").toString());
            priviRoleMenu.setMenuId(menuId);
            priviRoleMenu.setCreateUser(userId);
            priviRoleMenu.setUpdateUser(userId);
            priviRoleMenu.setCreateTime(DateTimeUtil.getStrFromNewDate());
            priviRoleMenu.setUpdateTime(DateTimeUtil.getStrFromNewDate());
            priviRoleMenu.setAppId(paramMap.get("appId").toString());
            priviRoleMenuMapper.insertSelective(priviRoleMenu);
            paramMap.put("menuId", menuId);
            roleCustomMapper.delRoleMenuInter(paramMap);
            roleCustomMapper.addRoleMenuInter(paramMap);
        }
        Map<String, Object> userMap = new HashMap<>();
        userMap.put("userId", userId);
        List<PriviInterCustom> allInters = commonMapper.selAllInterByUserId(userMap);
        UserInfo userInfo = (UserInfo)redisTemplate.opsForValue().get(token);
        userInfo.setAllInters(allInters);
        userInfo.setAllIntersFlag("1");
        if (redisTemplate.hasKey(token)) {
            redisTemplate.delete(token);
        }
        redisTemplate.opsForValue().set(token, userInfo, 24L, TimeUnit.HOURS);
        //redisTemplate.opsForValue().set(token + "allInters", allInters, 24L, TimeUnit.HOURS);
    }

    /**
     *查询某法人所有角色
     * @param paramMap
     * @return
     */
    public Result selAllRole(Map<String, Object> paramMap) {
        return Result.ok(roleCustomMapper.selAllRole(paramMap));
    }

    public Result queryAllMenu(String appId) {
        return Result.ok(roleCustomMapper.queryAllMenu(appId));
    }

    public Result queryMenuInter(Map<String, Object> map, Page page) {
        if (page != null && page.getPageIndex() != null && page.getPageSize() != null) {
            PageHelper.startPage(page.getPageIndex(), page.getPageSize());
        }
        Integer pageIndex = page.getPageIndex();
        Integer pageSize = page.getPageSize();
        List<Map<String, Object>> roleList = new ArrayList<>();
        if (!StringUtil.isEmpty(map.get("menuId"))) {
            roleList = roleCustomMapper.queryMenuInterRes(map);
        } else {
            roleList = roleCustomMapper.queryRoleInterRes(map);
        }
        List<String> idList = new ArrayList<>();
        Integer start = (pageIndex - 1) * pageSize + 1;
        for (int i = 0; i < roleList.size(); i++) {
            idList.add(roleList.get(i).get("resId").toString());
            roleList.get(i).put("seqNo", start);
            start++;
        }
        List<Map<String, Object>> list = new ArrayList<>();
        if (idList.size() > 0) {
            map.put("idList", idList);
            list = roleCustomMapper.queryMenuInter(map);
        }
        List<Map<String, Object>> interList = new ArrayList<>();
        List<Integer> indexList = new ArrayList<>();
        for (int i = 0; i < list.size(); i++) {
            boolean flag = false;
            for (int j = 0; j < indexList.size(); j++) {
                if (i == indexList.get(j)) {
                    flag = true;
                    break;
                }
            }
            if (!flag) {
                for (int j = 0; j < list.size(); j++) {
                    if (i != j && list.get(i).get("resId").toString().equals(list.get(j).get("resId").toString())) {
                        indexList.add(j);
                        if (!StringUtil.isEmpty(list.get(i).get("cnName"))) {
                            if (!StringUtil.isEmpty(list.get(j).get("cnName"))) {
                                list.get(i).put("cnName", list.get(i).get("cnName").toString() + "," + list.get(j).get("cnName").toString());
                            }
                        } else {
                            if (!StringUtil.isEmpty(list.get(j).get("cnName"))) {
                                list.get(i).put("cnName", list.get(j).get("cnName").toString());
                            }
                        }
                    }
                }
                interList.add(list.get(i));
            }
        }
        for (int i = 0; i < roleList.size(); i++) {
            for (int j = 0; j < interList.size(); j++) {
                if (roleList.get(i).get("resId").toString().equals(interList.get(j).get("resId").toString())) {
                    if (!StringUtil.isEmpty(interList.get(j).get("cnName"))) {
                        roleList.get(i).put("cnName", interList.get(j).get("cnName").toString());
                    }
                    break;
                }
            }
        }
        return Result.ok(new PageInfo(roleList).getTotal(), roleList);
    }

    @Transactional
    public void saveInterAuth(Map<String, Object> paramMap, HttpServletRequest request) {
        String token = request.getHeader(jwtTokenConfig.getHeader());
        UserInfo userInfo = (UserInfo)redisTemplate.opsForValue().get(token);
        List<Map<String, Object>> addList = (List<Map<String, Object>>)paramMap.get("addList");
        roleCustomMapper.delRoleInter(paramMap);
        for (int i = 0; i < addList.size(); i++) {
            Map<String, Object> map = new HashMap<>();
            map.put("roleId", paramMap.get("roleId").toString());
            map.put("resId", addList.get(i).get("resId").toString());
            map.put("userId", userInfo.getUserId());
            map.put("time", DateTimeUtil.getDate());
            roleCustomMapper.delSingleRoleInter(map);
            roleCustomMapper.addRoleInter(map);
        }
        Map<String, Object> map1 = new HashMap<>();
        map1.put("positionId", userInfo.getPositionId());
        map1.put("roleId", paramMap.get("roleId").toString());
        List<Map<String, Object>> list = roleCustomMapper.selPosRoleByInfo(map1);
        if (list != null && list.size() > 0) {
            map1.put("userId", userInfo.getUserId());
            List<PriviInterCustom> list2 = priviMenuInterCustomMapper.selRoleMenuByUserPosId(map1);
            userInfo.setPositionMenus(list2);
            userInfo.setMenuFlag("0");
            //redisTemplate.opsForValue().set(token + "positionMenus", list2, 24L, TimeUnit.HOURS);
            //redisTemplate.opsForValue().set(token + "menuFlag", "0", 24L, TimeUnit.HOURS);
        }
        Map<String, Object> userMap = new HashMap<>();
        userMap.put("userId", userInfo.getUserId());
        List<PriviInterCustom> allInters = commonMapper.selAllInterByUserId(userMap);
        userInfo.setAllInters(allInters);
        userInfo.setAllIntersFlag("1");
        if (redisTemplate.hasKey(token)) {
            redisTemplate.delete(token);
        }
        redisTemplate.opsForValue().set(token, userInfo, 24L, TimeUnit.HOURS);
        //redisTemplate.opsForValue().set(token + "allInters", allInters, 24L, TimeUnit.HOURS);
    }

    public Result queryBtnRes(Map<String, Object> paramMap) {
        return Result.ok(roleCustomMapper.queryBtnRes(paramMap));
    }

}
